package org.az.netty_study.p12_协议;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.logging.LoggingHandler;

import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_LENGTH;

/**
 * http的协议
 */
public class _2_Http的协议 {
    public static void main(String[] args) throws InterruptedException {
        new ServerBootstrap()
                .group(new NioEventLoopGroup())
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new LoggingHandler());
                        /**
                         * HttpServerCodec既是入站handler也是出站handler
                         * 入站时，将原始数据解析成两部分，1.请求行请求头，2.请求体
                         * 然后将这两部分分别传给下一个handler
                         * 下一个handler可以设置它感兴趣的对象类型
                         */
                        ch.pipeline().addLast(new HttpServerCodec());
                        /**
                         * SimpleChannelInboundHandler也是一个入站处理器，泛型是这个handler感兴趣的对象类型
                         * 只有从上一个handler传过来的msg是该handler感兴趣的对象类型，才会处理
                         */
                        ch.pipeline().addLast(new SimpleChannelInboundHandler<HttpRequest>() {
                            @Override
                            protected void channelRead0(ChannelHandlerContext ctx, HttpRequest msg) throws Exception {
                                //打印请求行
                                System.out.println(msg.uri());
                                //打印请求头
                                System.out.println(msg.headers());

                                //返回响应DefaultFullHttpResponse,DefaultFullHttpResponse出站时进过HttpServerCodec后，会被解析成字节数组
                                DefaultFullHttpResponse res = new DefaultFullHttpResponse(msg.protocolVersion(), HttpResponseStatus.OK);
                                byte[] body = "<h1>hello http!!!</h1>".getBytes();
                                //响应头加一个Content-Length，告诉浏览器响应体长度，否则浏览器会认为响应未完成一直傻傻转圈
                                res.headers().setInt(CONTENT_LENGTH, body.length);
                                //写入响应体数据
                                res.content().writeBytes(body);
                                ctx.writeAndFlush(res);
                            }
                        });
                    }
                }).bind(8888);
    }
}
